package com.dede.getmusic.util

import android.util.Base64

import java.io.IOException
import java.io.UnsupportedEncodingException
import java.net.URLEncoder
import java.security.GeneralSecurityException

import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec

/**
 * @author hsh
 * @date 2017/10/9 14:35.
 * @doc 网易云web版试听文件链接生成， {http://blog.csdn.net/Ciiiiiing/article/details/62434438}
 *
 *
 * request url:http://music.163.com/weapi/song/enhance/player/url? + [generateParams()][AES]
 * method post
 *
 *
 * example:
 * http://music.163.com/weapi/song/enhance/player/url?
 * params=f4sD8PGSoof%2FM8ohcUvLw2AkjMU%2BZinG86ncPj2JFOREu2PIIo9Tu4CuXf%2
 * FSbH0a88TmIGnDoWu0%0D%0AJFH9hbqcDmQlzBqZstKoW62fCMUhlMSOfT9LEaaWF9YOGuZ%2BT2QJ&encSecKey=
 * 257348aecb5e556c066de214e531faadd1c55d814f9be95fd06d6bff9f4c7a41f831f6394d5a3fd2e388173
 * 6d94a02ca919d952872e7d0a50ebfa1769a7a62d512f5f1ca21aec60bc3819a9c3ffca5eca9a0dba6d6f7249b06f5965
 * ecfff3695b54e1c28f3f624750ed39e7de08fc8493242e26dbc4484a01c76f739e135637c
 */
object AES {

    // 加密
    @Throws(GeneralSecurityException::class)
    private fun encrypt(sSrc: String?, sKey: String?): String? {
        if (sKey == null) {
            print("Key为空null")
            return null
        }
        // 判断Key是否为16位
        if (sKey.length != 16) {
            print("Key长度不是16位")
            return null
        }
        val raw = sKey.toByteArray()
        val skeySpec = SecretKeySpec(raw, "AES")
        val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")//"算法/模式/补码方式"
        val iv = IvParameterSpec("0102030405060708".toByteArray())//使用CBC模式，需要一个向量iv，可增加加密算法的强度
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv)
        val encrypted = cipher.doFinal(sSrc!!.toByteArray())

        return Base64.encodeToString(encrypted, Base64.DEFAULT)//此处使用BASE64做转码功能，同时能起到2次加密的作用。
    }

    // 解密
    private fun decrypt(sSrc: String, sKey: String?): String? {
        try {
            // 判断Key是否正确
            if (sKey == null) {
                print("Key为空null")
                return null
            }
            // 判断Key是否为16位
            if (sKey.length != 16) {
                print("Key长度不是16位")
                return null
            }
            val raw = sKey.toByteArray(charset("UTF-8"))
            val skeySpec = SecretKeySpec(raw, "AES")
            val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
            val iv = IvParameterSpec("0102030405060708"
                    .toByteArray())
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv)
            val encrypted1 = Base64.decode(sSrc, Base64.DEFAULT)//先用base64解密
            val original = cipher.doFinal(encrypted1)
            return String(original)
        } catch (ex: GeneralSecurityException) {
            println(ex.toString())
            return null
        } catch (ex: IOException) {
            println(ex.toString())
            return null
        }

    }

    @Throws(GeneralSecurityException::class)
    private fun generateFirstParams(text: String): String? {
        val firstKey = "0CoJUm6Qyw8W8jud"
        val secondKey = "FFFFFFFFFFFFFFFF"
        var hEncText = AES.encrypt(text, firstKey)
        hEncText = AES.encrypt(hEncText, secondKey)
        return hEncText
    }

    private val encSecKey: String
        get() = "257348aecb5e556c066de214e531faadd1c55d814f9be95fd06d6bff9f4c7a41f831f6394d5a3fd2e3881736d94a02ca919d952872e7d0a50ebfa1769a7a62d512f5f1ca21aec60bc3819a9c3ffca5eca9a0dba6d6f7249b06f5965ecfff3695b54e1c28f3f624750ed39e7de08fc8493242e26dbc4484a01c76f739e135637c"


    @Throws(GeneralSecurityException::class, UnsupportedEncodingException::class)
    fun generateParams(id: String): String {
        /*
         * 加密用的Key 可以用26个字母和数字组成，最好不要用保留字符，虽然不会错，至于怎么裁决，个人看情况而定
         * 此处使用AES-128-CBC加密模式，key需要为16位。
         */
        val firstParam = "{\"ids\":\"[$id]\",\"br\":128000,\"csrf_token\":\"\"}"
        return URLEncoder.encode(AES.generateFirstParams(firstParam), "UTF-8") + "&encSecKey=" + AES.encSecKey
    }

    @Throws(GeneralSecurityException::class, UnsupportedEncodingException::class)
    fun createRequestLink(id: String): String {
        return "http://music.163.com/weapi/song/enhance/player/url?params=" + generateParams(id)
    }
}
